//变量作用域和解构赋值
//变量在函数体内部声明，则该变量的作用域为整个函数体
//嵌套函数，内部函数可以引用外部函数的变量，反过来则不行

"use strict";
function foo1() {
  var x = 1;
  function bar() {
    var y = x + 1;
    console.log("内部函数调用外部y值为=" + y);
  }
  bar();
  //不能在这里写 var z=y+1;
}

foo1();

function foo() {
  var x = 1;
  function bar() {
    var x = "A";
    console.log("x in bar() = " + x); // 'A'
  }
  console.log("x in foo() = " + x); // 1
  bar();
}
foo();

//变量重名：当内部函数和外部函数重名怎么办？
function foo3() {
  var x = 1;
  function bar() {
    var x = "A";
    console.log("x in bar() = " + x); // 'A'
  }
  console.log("x in foo() = " + x); // 1
  bar();
} //从内部开始搜索，内部会屏蔽外部的变量

foo3();

//变量提升：JavaScript函数的特点，会先扫描整个函数体的语句，把所有申明的变量“提升”到函数顶部
//但是不提升赋值
function foo4() {
  var x = "hello" + y; //不会报错
  console.log(x); //但是这里输出是 hello undefined
  var y = "Bob";
}
//上述代码等价于
function foo5() {
  var y; // 提升变量y的申明，此时y为undefined
  var x = "Hello, " + y;
  console.log(x);
  y = "Bob";
}

//全局作用域 javascript有一个默认的对象window(代表的是一个浏览器的窗口，由浏览器创建)
//全局作用域的变量实际上都被绑定到该对象的属性上
var course = "Learn JavaScript";
alert(course);
alert(window.course);

//定义块级作用域的变量,使用let定义块级作用域
function foo() {
  var sum = 0;
  for (let i = 0; i < 100; i++) {
    sum += i;
  }
}

//解构赋值,传统的赋值方式如下
var array = ['hello', 'JavaScript', 'ES6'];
var x = array[0];
var y = array[1];
var z = array[2];

//解构赋值的方式如下:
var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
let [, , z] = ['hello', 'JavaScript', 'ES6'];//可以省略

//可以对对象进行解构赋值
var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
};
var {name, age, passport} = person;

//嵌套结构的解构
var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school',
    address: {
        city: 'Beijing',
        street: 'No.1 Road',
        zipcode: '100001'
    }
};
var {name, address: {city, zip}} = person;//address不是变量


//给id赋予passport的值
var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
};

let {name,passport:id}=person;//这里的:是使得变量名和属性名不一致
let {name,single=true}=person;//使用默认赋值，没有single属性的时候

//解构赋值的使用场景
//1、交换两个变量的值
var x=1,y=2;
[x,y]=[y,x];
//2、快速获取当前页面的域名和路径
var {hostname:domain, pathname:path} = location;
//3、当函数接受一个对象作为参数的时候，可以使用解构直接把对象的属性绑定到变量中
function buildDate({year, month, day, hour=0, minute=0, second=0}) {
    return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}
buildDate({ year: 2017, month: 1, day: 1 });
